package com.gitee.zycra.future.job.dao;

import com.gitee.zycra.future.job.common.bo.JobCalculateBO;
import com.gitee.zycra.future.job.common.model.JobSchedule;
import com.gitee.zycra.future.job.common.vo.JobScheduleNameVO;
import com.gitee.zycra.jdbc.common.BaseDao;
import com.gitee.zycra.jdbc.common.CommonSelector;
import com.gitee.zycra.jdbc.enums.SQLConditionEnum;
import com.gitee.zycra.jdbc.enums.SQLLinkEnum;
import com.gitee.zycra.jdbc.util.SQLBlock;
import com.gitee.zycra.jdbc.util.SQLChain;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Repository;

import java.time.LocalDateTime;
import java.util.List;

/**
 * @author zycra
 */
@Repository
public class JobScheduleDao extends BaseDao<JobSchedule> {

    @Autowired
    private CommonSelector commonSelector;

    /**
     * 插入
     *
     * @param jobSchedule 执行信息对象
     * @return 插入条数
     */
    public int insertJobSchedule(JobSchedule jobSchedule) {
        return insertIntoTable(jobSchedule);
    }

    /**
     * 更新
     *
     * @param jobSchedule 执行信息对象
     * @return 更新条数
     */
    public int updateJobSchedule(JobSchedule jobSchedule) {
        return updateTableById(jobSchedule, false);
    }

    /**
     * 根据元数据ID查询
     *
     * @param jobMetaDataId 元数据ID
     * @return 查询结果
     */
    public List<JobSchedule> selectJobScheduleByJobMetaDataId(Long jobMetaDataId) {
        return selectTableByNotNullColumnEquals(new JobSchedule().setDeleted(false).setJobMetaDataId(jobMetaDataId));
    }

    /**
     * 根据元数据ID查询数量
     *
     * @param jobMetaDataId 元数据ID
     * @return 查询结果
     */
    public Integer countJobScheduleByJobMetaDataId(Long jobMetaDataId) {
        return countTableByNotNullColumnEquals(new JobSchedule().setDeleted(false).setJobMetaDataId(jobMetaDataId));
    }

    /**
     * 根据ID查询
     *
     * @param jobScheduleId 任务调度ID
     * @return 任务调度对象
     */
    public JobSchedule selectById(Long jobScheduleId) {
        return selectTableById(new JobSchedule().setId(jobScheduleId));
    }

    /**
     * 根据ID计数
     *
     * @param idList id集合
     * @return 数量
     */
    public Integer countByIdList(List<Long> idList) {
        SQLChain sqlChain = SQLChain.builder()
                .addBlock(SQLBlock.of(SQLLinkEnum.AND, "id", SQLConditionEnum.IN, idList.toArray()))
                .build();
        return commonSelector.selectOneByParam(getJdbcTemplate(),
                "SELECT COUNT(*) FROM job_schedule" + sqlChain.getSQL(),
                Integer.class, sqlChain.getParamList());
    }

    /**
     * 查询待重新计算的执行信息
     *
     * @param startTime 起始时间
     * @param endTime   结束时间
     * @return 待重新计算的执行信息
     */
    public List<JobCalculateBO> selectJobForCalculate(LocalDateTime startTime, LocalDateTime endTime) {
        SQLChain sqlChain = SQLChain.builder()
                .addBlock(SQLBlock.of(SQLLinkEnum.AND, "js.next_schedule_time", SQLConditionEnum.GREATER_THAN, startTime))
                .addBlock(SQLBlock.of(SQLLinkEnum.AND, "js.next_schedule_time", SQLConditionEnum.LESS_THAN, endTime))
                .build();
        return commonSelector.selectByParam(getJdbcTemplate(),
                "SELECT js.id, jmd.job_name, js.schedule_name, jmd.job_class_name, jmd.application_name, js.schedule_param, jsl.retry_times, "
                        + "jsl.schedule_ratio, jsl.node_ip, jmd.job_retry_interval, jmd.job_retry_times, jmd.job_cycle, js.last_schedule_time, "
                        + "js.next_schedule_time, js.normal_next_time, js.cron_month, js.cron_day, js.cron_hour, js.cron_minute, js.cron_second "
                        + "FROM job_schedule js INNER JOIN job_meta_data jmd ON js.job_meta_data_id = jmd.id AND js.schedule_enable = 1 AND js"
                        + ".deleted = 0 AND jmd.deleted = 0 LEFT JOIN job_schedule_log jsl ON js.id = jsl.job_schedule_id AND js.last_schedule_time"
                        + " = jsl.schedule_time " + sqlChain.getSQL()
                        + " AND NOT EXISTS(SELECT 1 FROM job_running jr WHERE jr.job_schedule_id = js.id)",
                JobCalculateBO.class, sqlChain.getParamList(), false);
    }

    /**
     * 查询所有任务信息
     *
     * @param jobCycle          执行周期
     * @param currentScheduleId 当前调度信息ID
     * @return 所有任务信息
     */
    public List<JobScheduleNameVO> selectAllSchedule(Integer jobCycle, Long currentScheduleId) {
        SQLChain sqlChain = SQLChain.builder()
                .addBlock(SQLBlock.of(SQLLinkEnum.AND, "jmd.job_cycle", SQLConditionEnum.EQUALS, jobCycle))
                .addBlock(SQLBlock.of(SQLLinkEnum.AND, "js.id", SQLConditionEnum.NOT_EQUALS, currentScheduleId))
                .build();
        return commonSelector.selectByParam(getJdbcTemplate(),
                "SELECT js.id, js.schedule_name, jmd.job_name FROM job_schedule js INNER JOIN job_meta_data jmd ON js.job_meta_data_id = jmd.id AND"
                        + " js.deleted = 0 AND jmd.deleted = 0" + sqlChain.getSQL(), JobScheduleNameVO.class, sqlChain.getParamList());
    }

    /**
     * 根据调度配置ID查询调度周期
     *
     * @param jobScheduleId 调度配置ID
     * @return 调度周期
     */
    public Integer selectJobCycleByJobScheduleId(Long jobScheduleId) {
        return commonSelector.selectOneByParam(getJdbcTemplate(),
                "SELECT jmd.job_cycle FROM job_meta_data jmd INNER JOIN job_schedule js ON jmd.id = js.job_meta_data_id AND jmd.deleted = 0 AND "
                        + "js.deleted = 0 WHERE js.id = ?", Integer.class, List.of(jobScheduleId), false);
    }
}
